/**
 * Copyright (C) 2018-2022
 * All rights reserved, Designed By www.yixiang.co
 * 注意：
 * 本软件为www.yixiang.co开发研制，未经购买不得使用
 * 购买后可获得全部源代码（禁止转卖、分享、上传到码云、github等开源平台）
 * 一经发现盗用、分享等行为，将追究法律责任，后果自负
 */
package co.yixiang.yshop.module.pay.controller.app;

import co.yixiang.yshop.framework.common.pojo.CommonResult;
import co.yixiang.yshop.framework.security.core.annotations.PreAuthenticated;
import co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils;
import co.yixiang.yshop.module.member.api.user.MemberUserApi;
import co.yixiang.yshop.module.member.api.user.dto.MemberUserRespDTO;
import co.yixiang.yshop.module.pay.controller.admin.merchantdetails.vo.PayParam;
import co.yixiang.yshop.module.pay.controller.app.vo.AppPayParam;
import co.yixiang.yshop.module.pay.dal.dataobject.merchantdetails.MerchantDetailsDO;
import co.yixiang.yshop.module.pay.enums.PayOrderConstants;
import co.yixiang.yshop.module.pay.enums.PayTypeEnum;
import co.yixiang.yshop.module.pay.processor.PayOrderProcessor;
import co.yixiang.yshop.module.pay.service.merchantdetails.MerchantDetailsService;
import co.yixiang.yshop.module.pay.strategy.PayClient;
import co.yixiang.yshop.module.pay.strategy.PayClientFactory;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Map;
import java.util.Objects;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.framework.common.pojo.CommonResult.success;
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.USER_NOT_BINDING_WX;
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.USER_NOT_BINDING_WX_APPLET;

/**
 * 统一支付
 */
@Slf4j
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Tag(name = "APP - 支付模块")
@RequestMapping("/pay")
public class AppPayController {

    @Resource
    private PayClientFactory payClientFactory;

    @Resource
    private PayOrderProcessor payOrderProcessor;

    @Resource
    private MerchantDetailsService merchantDetailsService;

    @Resource
    private MemberUserApi memberUserApi;

    @PreAuthenticated
    @PostMapping(value = "/payment")
    @Operation(summary = "统一支付")
    public CommonResult<Map<String, String>> payment(@Valid @RequestBody AppPayParam param) throws Exception {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("=========进入统一支付，param参数:{}", param.toString());
        //支付类型
        String payType = param.getPayType();
        //订单id
        String orderId = param.getOrderId();

        MerchantDetailsDO merchantDetailsDO = merchantDetailsService.getMerchantByType(payType);
        // 获取支付客户端
        PayClient client = payClientFactory.getClient(payType);
        // 处理规则
        PayParam payParam = payOrderProcessor.getPayParam(orderId, payType);
        log.info("=========处理规则后，payParam参数:{}", payParam.toString());
        //如果是小程序或APP 先获取用户openid
        MemberUserRespDTO user = memberUserApi.getUser(userId);

        log.info("=========用戶，MemberUserRespDTO参数:{}", user.toString());
        if (PayTypeEnum.WEIXIN_APPLET.getType().equals(payType)) {
            //小程序支付需要openid
            if (Objects.isNull(user.getRoutineOpenId())) throw exception(USER_NOT_BINDING_WX_APPLET);
        }
        if (PayTypeEnum.WEIXIN.getType().equals(payType)) {
            //小程序支付需要openid
            if (Objects.isNull(user.getRoutineOpenId())) throw exception(USER_NOT_BINDING_WX);
        }
        payParam.setType(payType);
        payParam.setMerchantDetailsDO(merchantDetailsDO);
        payParam.setUid(userId);
        Boolean helpPay = param.getHelpPay();
        //是否为代付
        payParam.setHelpPay(helpPay);

        // 拉起支付
        Map<String, String> payment = client.payment(payParam);
        log.info("=========拉起支付，payment:{}", payParam);
        payOrderProcessor.handelWait(orderId, payment);
        return success(payment);
    }

    @RequestMapping("/wxPayNotify")
    @Operation(summary = "统一微信支付回调")
    @PermitAll
    public void wxPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 处理回调
        payOrderProcessor.handleWeChatPayNotify(request);
        response.getWriter().write(PayOrderConstants.WEINXIN_RESULT);
    }

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @RequestMapping("/flush")
    @Operation(summary = "清空redis")
    @PermitAll
    public void flush() throws Exception {
        redisTemplate.execute((RedisCallback<Void>) connection -> {
            connection.flushDb();
            return null;
        });
    }

}

